home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / ipacl / ipacl.y < prev    next >
Encoding:
Text File  |  1992-06-24  |  13.5 KB  |  721 lines

  1.  
  2. /* Copyright (C) Gerhard Fuernkranz 1992 */
  3.  
  4. %{
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <stdarg.h>
  11. #include <netdb.h>
  12. #include <stropts.h>
  13.  
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18.  
  19. #include "matcher.h"
  20.  
  21. #define GEN1(a)        gen1(a,#a)
  22. #define GEN2(a,b)    gen2(a,#a,b)
  23. #define GEN3(a,b)    gen3(a,#a,b)
  24. #define GEN4(a,b)    gen4(a,#a,b)
  25. #define GEN5(a,b)    gen5(a,#a,b)
  26.  
  27. typedef enum set_type {
  28.     port_set, addr_set
  29. } SET_TYPE;
  30.  
  31. typedef struct sym SYM;            /* forward */
  32.  
  33. typedef struct fix {            /* for fixing forw. ref. */
  34.     struct fix *next;
  35.     unsigned short where;
  36. } FIX;
  37.  
  38. typedef struct addr {            /* inet-addr/network w/ mask */
  39.     unsigned long addr;        /* inet address */
  40.     unsigned long mask;        /* netmask */
  41. } ADDR;
  42.  
  43. typedef struct port {            /* Port protocol & port number */
  44.     unsigned short proto;        /* protocol */
  45.     unsigned short port;        /* port number */
  46. } PPORT;
  47.  
  48. typedef struct set {            /* specify addres/port set */
  49.     struct set *next;
  50.     SET_TYPE type;            /* which kind of set (port/addr/...) */
  51.     unsigned short count;        /* # of elements */
  52.     void *ptr;            /* data */
  53.     SYM *label;            /* label to represent this set */
  54.     int referenced;            /* set has been referenced */
  55. } SET;
  56.  
  57. struct sym {                /* symbol table entry */
  58.     struct sym    *next;
  59.     char        *name;
  60.     int        token;        /* symbol's token value */
  61.     int        label_pc;    /* symbol's label value */
  62.     FIX        *fixlist;    /* fwd. refs to fix */
  63.     union {
  64.         PPORT    port;        /* for port names */
  65.         ADDR    addr;        /* for host/net names */
  66.         SET        *set;        /* for addr/port sets */
  67.     } u;
  68. };
  69.  
  70. #define sym_addr    u.addr
  71. #define sym_port    u.port
  72. #define sym_set        u.set
  73.  
  74. static int errors;            /* # of errors occured */
  75.  
  76. static PPORT ports[4096];        /* table to build port sets */
  77. static PPORT *pptr;
  78.  
  79. static ADDR addrs[4096];        /* table to build addr sets */
  80. static ADDR *aptr;
  81.  
  82. static unsigned short program[16*1024]; /* The program we produce */
  83. static unsigned short *pc = program;
  84.  
  85. static SYM *symtab;            /* head of symbol table */
  86. static SET *settab;            /* head of set table */
  87.  
  88. static void error(const char *, ...);
  89. static void yyerror(const char *s);
  90. static unsigned long netmask(unsigned long);
  91. static SYM *lookup(const char *name);
  92. static SYM *new_label(void);
  93. static SET *new_set(SET_TYPE type);
  94.  
  95. %}
  96.  
  97. %union {
  98.     long    intval;
  99.     SYM    *sym;
  100.     SET    *set;
  101.     char    *str;
  102.     ADDR    addr;
  103.     PPORT    port;
  104. }
  105.  
  106. %token ACCEPT
  107. %token DENY
  108. %token DST
  109. %token GOTO
  110. %token HOST
  111. %token IN
  112. %token MASK
  113. %token NET
  114. %token PORT
  115. %token SRC
  116.  
  117. %token <str>        STRING
  118. %token <str>        DOTTED
  119.  
  120. %token <intval>        NUMBER
  121.  
  122. %token <intval>        PROTOCOL
  123.  
  124. %token <sym>        LABEL
  125. %token <sym>        NAME
  126. %token <sym>        PORT_NAME
  127. %token <sym>        PORT_SET_NAME
  128. %token <sym>        ADDR_NAME
  129. %token <sym>        ADDR_SET_NAME
  130.  
  131. %type <port>        port
  132. %type <addr>        addr
  133. %type <addr>        addr_prefix
  134. %type <set>        port_set
  135. %type <set>        addr_set
  136. %type <sym>        anyname
  137.  
  138. %%
  139.  
  140. program:  /* empty */
  141.     | program rule
  142.     ;
  143.  
  144. port:      NUMBER
  145.         { $$.port = $1; $$.proto = 6; /* TCP */ }
  146.     | PORT NUMBER
  147.         { $$.port = $2; $$.proto = 6; /* TCP */ }
  148.     | NUMBER '/' PROTOCOL
  149.         { $$.port = $1; $$.proto = $3; }
  150.     | PORT NUMBER '/' PROTOCOL
  151.         { $$.port = $2; $$.proto = $4; }
  152.     | PORT STRING
  153.         {
  154.             char *p;
  155.             struct servent *sp;
  156.             struct protoent *pp;
  157.             if ((p = strchr($2,'/')) == NULL)
  158.             p = "tcp";
  159.             else
  160.             *p++ = 0;
  161.             if ((pp = getprotobyname(p)) == NULL) {
  162.             error("Unknown protocol '%s'\n",p);
  163.             $$.proto = 6; /* TCP */
  164.             }
  165.             else {
  166.             $$.proto = pp->p_proto;
  167.             }
  168.             if ((sp = getservbyname($2,p)) == NULL) {
  169.             error("Unknown service '%s/%s'\n",$2,p);
  170.             $$.port = 0;
  171.             }
  172.             else {
  173.             $$.port = ntohs(sp->s_port);
  174.             }
  175.         }
  176.     | PORT_NAME
  177.         { $$ = $1->sym_port; }
  178. /* conflict
  179.     | NAME
  180.         { $$ = 0; error("Name '%s' undefined\n",$1->name); }
  181. */
  182.     ;
  183.  
  184. addr:      addr_prefix
  185.     | addr_prefix MASK NUMBER
  186.         { $$ = $1; $$.addr &= $3; $$.mask = $3; }
  187.     ;
  188.  
  189. addr_prefix:
  190.       HOST NUMBER
  191.         { $$.addr = $2; $$.mask = 0xffffffff; }
  192.     | HOST DOTTED
  193.         {
  194.             $$.addr = ntohl(inet_addr($2));
  195.             if ($$.addr == -1)
  196.             error("Illegal internet address '%s'\n",$2);
  197.             $$.mask = 0xffffffff;
  198.         }
  199.     | DOTTED
  200.         {
  201.             $$.addr = ntohl(inet_addr($1));
  202.             if ($$.addr == -1)
  203.             error("Illegal internet address '%s'\n",$1);
  204.             $$.mask = 0xffffffff;
  205.         }
  206.     | HOST STRING
  207.         {
  208.             struct hostent *hp;
  209.             if ((hp = gethostbyname($2)) != NULL) {
  210.             $$.addr = ntohl(*(long*)hp->h_addr);
  211.             }
  212.             else {
  213.             error("Unknown host '%s'\n",$2);
  214.             $$.addr = 0;
  215.             }
  216.             $$.mask = 0xffffffff;
  217.         }
  218.     | NET NUMBER
  219.         {
  220.             unsigned long net = $2;
  221.             $$.addr = ntohl(inet_makeaddr(net,0).s_addr);
  222.             $$.mask = netmask($$.addr);
  223.         }
  224.     | NET DOTTED
  225.         {
  226.             unsigned long net = inet_network($2);
  227.             if (net == -1)
  228.             error("Illegal network '%s'\n",$2);
  229.             $$.addr = ntohl(inet_makeaddr(net,0).s_addr);
  230.             $$.mask = netmask($$.addr);
  231.         }
  232.     | NET STRING
  233.         {
  234.             struct netent *np;
  235.             unsigned long net = 0;
  236.             if ((np = getnetbyname($2)) != NULL)
  237.             net = np->n_net;
  238.             else
  239.             error("Unknown network '%s'\n",$2);
  240.             $$.addr = ntohl(inet_makeaddr(net,0).s_addr);
  241.             $$.mask = netmask($$.addr);
  242.         }
  243.     | STRING
  244.         {
  245.             unsigned long net;
  246.             struct netent *np;
  247.             struct hostent *hp;
  248.             if ((hp = gethostbyname($1)) != NULL) {
  249.             $$.addr = ntohl(*(long*)hp->h_addr);
  250.             $$.mask = 0xffffffff;
  251.             }
  252.             else if ((np = getnetbyname($1)) != NULL) {
  253.             net = np->n_net;
  254.             $$.addr = ntohl(inet_makeaddr(net,0).s_addr);
  255.             $$.mask = netmask($$.addr);
  256.             }
  257.             else {
  258.             $$.addr = 0;
  259.             $$.mask = 0xffffffff;
  260.             error("Unknown host/network '%s'\n",$1);
  261.             }
  262.         }
  263.     | ADDR_NAME
  264.         { $$ = $1->sym_addr; }
  265. /* conflict
  266.     | NAME
  267.         { $$.addr = 0; $$.addr = 0xffffffff;
  268.           error("Name '%s' undefined\n",$1->name); }
  269. */
  270.     ;
  271.  
  272. port_set: '{' port_list '}'
  273.         {
  274.             int n;
  275.             $$ = new_set(port_set);
  276.             $$->count = pptr - ports;
  277.             n = $$->count * sizeof(ports[0]);
  278.             $$->ptr = memcpy(malloc(n),ports,n);
  279.         }
  280.     | PORT_SET_NAME
  281.         { $$ = $1->sym_set; }
  282.     ;
  283.  
  284. port_list:
  285.       port
  286.         { ports[0] = $1; pptr = ports+1; }
  287.     | PORT_SET_NAME
  288.         {
  289.             memcpy(ports,$1->sym_set->ptr,
  290.             $1->sym_set->count * sizeof(ports[0]));
  291.             pptr = ports + $1->sym_set->count;
  292.         }
  293.     | port_list ',' port
  294.         { *pptr++ = $3; }
  295.     | port_list ',' PORT_SET_NAME
  296.         {
  297.             memcpy(pptr,$3->sym_set->ptr,
  298.             $3->sym_set->count * sizeof(ports[0]));
  299.             pptr += $3->sym_set->count;
  300.         }
  301.     ;
  302.  
  303. addr_set: '{' addr_list '}'
  304.         {
  305.             int n;
  306.             $$ = new_set(addr_set);
  307.             $$->count = aptr - addrs;
  308.             n = $$->count * sizeof(addrs[0]);
  309.             $$->ptr = memcpy(malloc(n),addrs,n);
  310.         }
  311.     | ADDR_SET_NAME
  312.         { $$ = $1->sym_set; }
  313.     ;
  314.  
  315. addr_list:
  316.       addr
  317.         { addrs[0] = $1; aptr = addrs+1; }
  318.     | ADDR_SET_NAME
  319.         {
  320.             memcpy(addrs,$1->sym_set->ptr,
  321.             $1->sym_set->count * sizeof(ADDR));
  322.             aptr = addrs + $1->sym_set->count;
  323.         }
  324.     | addr_list ',' addr
  325.         { *aptr++ = $3; }
  326.     | addr_list ',' ADDR_SET_NAME
  327.         {
  328.             memcpy(aptr,$3->sym_set->ptr,
  329.             $3->sym_set->count * sizeof(ADDR));
  330.             aptr += $3->sym_set->count;
  331.         }
  332.     ;
  333.  
  334. def:      NAME '=' port
  335.         { $1->token = PORT_NAME; $1->sym_port = $3; }
  336.     | NAME '=' addr
  337.         { $1->token = ADDR_NAME; $1->sym_addr = $3; }
  338.     | NAME '=' port_set
  339.         { $1->token = PORT_SET_NAME; $1->sym_set = $3; }
  340.     | NAME '=' addr_set
  341.         { $1->token = ADDR_SET_NAME; $1->sym_set = $3; }
  342.     ;
  343.  
  344. cond:
  345.       SRC '=' '=' addr
  346.         { GEN3(SAEQ,$4); }
  347.     | SRC '!' '=' addr
  348.         { GEN3(SANE,$4); }
  349.     | SRC IN addr_set
  350.         { GEN4(SAIN,$3); }
  351.     | SRC '!' IN addr_set
  352.         { GEN4(SANIN,$4); }
  353.  
  354.     | DST '=' '=' addr
  355.         { GEN3(DAEQ,$4); }
  356.     | DST '!' '=' addr
  357.         { GEN3(DANE,$4); }
  358.     | DST IN addr_set
  359.         { GEN4(DAIN,$3); }
  360.     | DST '!' IN addr_set
  361.         { GEN4(DANIN,$4); }
  362.  
  363.     | SRC '=' '=' port
  364.         { GEN2(SPEQ,$4); }
  365.     | SRC '!' '=' port
  366.         { GEN2(SPNE,$4); }
  367.     | SRC '<' port
  368.         { GEN2(SPLT,$3); }
  369.     | SRC '>' port
  370.         { GEN2(SPGT,$3); }
  371.     | SRC '<' '=' port
  372.         { GEN2(SPLE,$4); }
  373.     | SRC '>' '=' port
  374.         { GEN2(SPGE,$4); }
  375.     | SRC IN port_set
  376.         { GEN4(SPIN,$3); }
  377.     | SRC '!' IN port_set
  378.         { GEN4(SPNIN,$4); }
  379.  
  380.     | DST '=' '=' port
  381.         { GEN2(DPEQ,$4); }
  382.     | DST '!' '=' port
  383.         { GEN2(DPNE,$4); }
  384.     | DST '<' port
  385.         { GEN2(DPLT,$3); }
  386.     | DST '>' port
  387.         { GEN2(DPGT,$3); }
  388.     | DST '<' '=' port
  389.         { GEN2(DPLE,$4); }
  390.     | DST '>' '=' port
  391.         { GEN2(DPGE,$4); }
  392.     | DST IN port_set
  393.         { GEN4(DPIN,$3); }
  394.     | DST '!' IN port_set
  395.         { GEN4(DPNIN,$4); }
  396.     ;
  397.  
  398. anyname:  NAME
  399.     | PORT_NAME
  400.     | PORT_SET_NAME
  401.     | ADDR_NAME
  402.     | ADDR_SET_NAME
  403.  
  404. rule:      def
  405.     | LABEL ':'
  406.         { gen_label($1); }
  407.     | cond '-' '>' ACCEPT
  408.         { GEN1(TACCEPT); }
  409.     | cond '-' '>' DENY
  410.         { GEN1(TDENY); }
  411.     | cond '-' '>' anyname
  412.         { GEN5(TJMP,$4); }
  413.     | ACCEPT
  414.         { GEN1(UACCEPT); }
  415.     | DENY
  416.         { GEN1(UDENY); }
  417.     | GOTO anyname
  418.         { GEN5(JMP,$2); }
  419.     | error
  420.     ;
  421.  
  422. %%
  423.  
  424. #include "lex.yy.c"
  425.  
  426. /* Print error message */
  427.  
  428. static void
  429. error(const char *fmt, ...)
  430. {
  431.     va_list ap;
  432.     va_start(ap,fmt);
  433.     fprintf(stderr,"Line %d: ",yylineno);
  434.     vfprintf(stderr,fmt,ap);
  435.     va_end(ap);
  436.     errors++;
  437. }
  438.  
  439. /* Report yacc error */
  440.  
  441. static void
  442. yyerror(const char *s)
  443. {
  444.     error("%s before or at '%s'\n",s,yytext);
  445. }
  446.  
  447. /* Compute the netmask for a given network number.  */
  448.  
  449. static unsigned long
  450. netmask(unsigned long net)
  451. {
  452.     if (IN_CLASSA(net))
  453.     return IN_CLASSA_NET;
  454.     if (IN_CLASSB(net))
  455.     return IN_CLASSB_NET;
  456.     return IN_CLASSC_NET;
  457. }
  458.  
  459. /* lookup a symbol in the symbol table */
  460.  
  461. SYM *
  462. lookup(const char *name)
  463. {
  464.     SYM *p;
  465.  
  466.     for (p = symtab; p; p = p->next)
  467.     if (strcmp(name,p->name) == 0)
  468.         return p;
  469.     p = calloc(1,sizeof(*p));
  470.     p->name = strdup(name);
  471.     p->next = symtab;
  472.     p->label_pc = -1;
  473.     symtab = p;
  474.     return p;
  475. }
  476.  
  477. /* Create a new set structure and link into table */
  478.  
  479. static SET *
  480. new_set(SET_TYPE type)
  481. {
  482.     SET *s;
  483.  
  484.     s = calloc(1,sizeof(*s));
  485.     s->type = type;
  486.     s->label = new_label();
  487.     s->next = settab;
  488.     settab = s;
  489.     return s;
  490. }
  491.  
  492. /* create a new symbol assciated with a label */
  493.  
  494. static SYM *
  495. new_label(void)
  496. {
  497.     static current_nr = 0;
  498.     int lab = ++current_nr;
  499.     char name[16];
  500.     SYM *sym;
  501.  
  502.     sprintf(name,"$L%d",lab);
  503.     sym = lookup(name);
  504.     return sym;
  505. }
  506.  
  507. /* produce assembler listing */
  508.  
  509. static void
  510. asmlist(int how, ...)
  511. {
  512.     int i = 0;
  513.     va_list ap;
  514.     const char *op;
  515.     const char *fmt;
  516.     static unsigned short *save_pc;
  517.  
  518.     if (how == 1) {
  519.         save_pc = pc;
  520.         return;
  521.     }
  522.     if (how == 3) {
  523.     va_start(ap,i);
  524.     op = va_arg(ap,const char *);
  525.     va_end(ap);
  526.     printf("%5d:\t\t%s:\n",pc-program,op);
  527.     return;
  528.     }
  529.     va_start(ap,i);
  530.     op = va_arg(ap,const char *);
  531.     fmt = va_arg(ap,const char *);
  532.     i += printf("%5d: ",save_pc - program);
  533.     while (save_pc < pc)
  534.     i += printf("%04x ",*save_pc++);
  535.     if (how == 4) {
  536.     printf("\n");
  537.     return;
  538.     }
  539.     if (i >= 24) {
  540.     printf("\n\t\t\t");
  541.     i = 24;
  542.     }
  543.     while (i < 24) {
  544.     putchar(' ');
  545.     i++;
  546.     }
  547.     printf("%-7s ",op);
  548.     vprintf(fmt,ap);
  549.     printf("\n");
  550.     va_end(ap);
  551. }
  552.  
  553. /* generate a long word */
  554.  
  555. static void
  556. gen_long(unsigned long l)
  557. {
  558.     *(unsigned long *) pc = l;
  559.     pc += sizeof(l) / sizeof(*pc);
  560. }
  561.  
  562. static void
  563. gen_label(SYM *label)
  564. {
  565.     if (label->label_pc >= 0)
  566.     error("Label '%s' multiply defined\n",label->name);
  567.     else
  568.     label->label_pc = pc - program;
  569.     asmlist(3,label->name);
  570. }
  571.  
  572. static void
  573. gen_label_ref(SYM *label)
  574. {
  575.     FIX *f;
  576.  
  577.     if (label->label_pc >= 0) {
  578.     *pc = label->label_pc - (pc - program);
  579.     pc++;
  580.     return;
  581.     }
  582.     f = malloc(sizeof(*f));
  583.     f->next = label->fixlist;
  584.     label->fixlist = f;
  585.     f->where = pc - program;
  586.     *pc++ = - (pc - program);
  587. }
  588.  
  589. static void
  590. gen1(OPCODE op, const char *opstr)
  591. {
  592.     asmlist(1);
  593.     *pc++ = op;
  594.     asmlist(2,opstr,"");
  595. }
  596.  
  597. static void
  598. gen2(OPCODE op, const char *opstr, PPORT port)
  599. {
  600.     asmlist(1);
  601.     *pc++ = op;
  602.     *pc++ = port.proto;
  603.     *pc++ = port.port;
  604.     asmlist(2,opstr,"%d,%d",(int)port.proto,(int)port.port);
  605. }
  606.  
  607. static void
  608. gen3(OPCODE op, const char *opstr, ADDR addr)
  609. {
  610.     asmlist(1);
  611.     *pc++ = op;
  612.     gen_long(htonl(addr.addr));
  613.     gen_long(htonl(addr.mask));
  614.     asmlist(2,opstr,"0x%08lx,0x%08lx",addr.addr,addr.mask);
  615. }
  616.  
  617. static void
  618. gen4(OPCODE op, const char *opstr, SET *set)
  619. {
  620.     asmlist(1);
  621.     *pc++ = op;
  622.     gen_label_ref(set->label);
  623.     *pc++ = set->count;
  624.     asmlist(2,opstr,"%s,%d",set->label->name,(int)set->count);
  625.     set->referenced = 1;
  626. }
  627.  
  628. static void
  629. gen5(OPCODE op, const char *opstr, SYM *label)
  630. {
  631.     asmlist(1);
  632.     *pc++ = op;
  633.     gen_label_ref(label);
  634.     asmlist(2,opstr,"%s",label->name);
  635. }
  636.  
  637. static void
  638. gen_sets(void)
  639. {
  640.     int i;
  641.     SET *s;
  642.     ADDR *pa = NULL;
  643.     PPORT *pp = NULL;
  644.  
  645.     for (s = settab; s; s = s->next) {
  646.     if (!s->referenced)
  647.         continue;
  648.     gen_label(s->label);
  649.     pp = s->ptr;
  650.     pa = s->ptr;
  651.     for (i = 0; i < s->count; i++) {
  652.         if (s->type == port_set) {
  653.         asmlist(1);
  654.         *pc++ = pp->proto;
  655.         *pc++ = pp->port;
  656.         pp++;
  657.         asmlist(4);
  658.         }
  659.         else {
  660.         asmlist(1);
  661.         gen_long(htonl(pa->addr));
  662.         gen_long(htonl(pa->mask));
  663.         pa++;
  664.         asmlist(4);
  665.         }
  666.     }
  667.     }
  668. }
  669.  
  670. /* Fix forward refs */
  671.  
  672. static void
  673. fix_forward(void)
  674. {
  675.     SYM *s;
  676.     FIX *f;
  677.  
  678.     printf("\nFixing forward references\n\n");
  679.     for (s = symtab; s; s = s->next) {
  680.     if (s->fixlist && s->label_pc < 0)
  681.         error("Undefined label '%s'\n",s->name);
  682.     else {
  683.         for (f = s->fixlist; f; f = f->next) {
  684.         program[f->where] += s->label_pc;
  685.         printf("%5d: %04x\n",(int)f->where,(int)program[f->where]);
  686.         }
  687.     }
  688.     }
  689. }
  690.  
  691. /* Main program */
  692.  
  693. void
  694. main(void)
  695. {
  696.     int fd;
  697.     struct strioctl io;
  698.  
  699.     yyparse();
  700.     GEN1(UDENY);
  701.     gen_sets();
  702.     fix_forward();
  703.     if (errors != 0) {
  704.     error("Found %d errors - aborting\n",errors);
  705.     exit(1);
  706.     }
  707.     if ((fd = open("/dev/ip",2)) == -1) {
  708.     perror("/dev/ip");
  709.     exit(1);
  710.     }
  711.     io.ic_cmd = 'I' << 24 | 'P' << 16 | 'A' << 8 | 0;
  712.     io.ic_timout = -1;
  713.     io.ic_len = (char*)pc - (char*)program;
  714.     io.ic_dp = (void*)program;
  715.     if (ioctl(fd,I_STR,&io) == -1) {
  716.     perror("ioctl");
  717.     exit(1);
  718.     }
  719. }
  720.  
  721.